package com.yike.order.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yike.common.base.BaseServiceImpl;
import com.yike.common.constant.CommonConstant;
import com.yike.common.constant.RocketMqConstant;
import com.yike.common.entity.CommissionOrderMq;
import com.yike.common.exception.BusinessException;
import com.yike.common.pagination.PageInfo;
import com.yike.common.pagination.Paging;
import com.yike.common.redis.RedisUtil;
import com.yike.common.tool.LoginUtil;
import com.yike.common.tool.StringUtil;
import com.yike.order.entity.Order;
import com.yike.order.entity.OrderDetail;
import com.yike.order.entity.Refund;
import com.yike.order.entity.RefundDetail;
import com.yike.order.mapper.OrderDetailMapper;
import com.yike.order.mapper.OrderMapper;
import com.yike.order.mapper.RefundDetailMapper;
import com.yike.order.mapper.RefundMapper;
import com.yike.order.param.*;
import com.yike.order.service.PlatformOrderService;
import com.yike.order.service.WxPayService;
import com.yike.order.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 平台订单
 *
 * @author Sakura
 * @since 2024-11-01
 */
@Slf4j
@Service
public class PlatformOrderServiceImpl extends BaseServiceImpl<OrderMapper, Order> implements PlatformOrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RefundMapper refundMapper;
    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private RefundDetailMapper refundDetailMapper;

    @Override
    public Paging<PlatformOrderVo> getOrderList(PlatformOrderPageParam platformOrderPageParam) throws Exception {
        Page<Order> page = new PageInfo<>(platformOrderPageParam);
        IPage<PlatformOrderVo> iPage = orderMapper.getOrderList(page, platformOrderPageParam);
        return new Paging<PlatformOrderVo>(iPage);
    }

    @Override
    public PlatformOrderInfoVo getOrderInfo(String orderNo) {
        PlatformOrderInfoVo platformOrderInfoVo = orderMapper.getPlatformOrderInfoVo(orderNo);
        if (platformOrderInfoVo == null) {
            throw new BusinessException("订单信息异常");
        }
        // 获取订单详情
        List<OrderDetailVo> orderDetailVos = orderDetailMapper.getOrderDetailVoByOrderId(platformOrderInfoVo.getId());
        platformOrderInfoVo.setOrderDetailVos(orderDetailVos);

        // 获取订单退款单号
        List<String> refundNos = refundMapper.getRefundNos(platformOrderInfoVo.getId());
        platformOrderInfoVo.setRefundNos(refundNos);

        return platformOrderInfoVo;
    }

    @Override
    @Transactional
    public boolean refund(RefundOrderParam refundOrderParam) throws ParseException {
        // 通过redis防止重复提交
        if (redisUtil.hasKey(CommonConstant.ORDER_REFUND_CHECK + refundOrderParam.getOrderNo())) {
            throw new BusinessException(500, "退款频率过快，请稍后再操作");
        }
        redisUtil.set(CommonConstant.ORDER_REFUND_CHECK + refundOrderParam.getOrderNo(), 1, 3);

        Order order = orderMapper.selectOne(Wrappers.lambdaQuery(Order.class)
                .eq(Order::getOrderNo, refundOrderParam.getOrderNo()));

        if (ObjectUtil.isNull(order)) {
            throw new BusinessException(500, "订单信息异常");
        }

        // 只有支付成功和部分退款的订单可以进行退款操作
        if (order.getStatus() != 1 && order.getStatus() != 4) {
            throw new BusinessException(500, "订单信息异常");
        }

        // 校验退款金额是否正常
        // 获取当前订单已退款金额
        BigDecimal beforeRefundFee = refundMapper.getRefundAmountByOrderId(order.getId());
        // 退款金额加已退款金额不得大于订单支付金额
        if (order.getAmount().compareTo(beforeRefundFee.add(refundOrderParam.getRefundFee())) < 0) {
            throw new BusinessException(500, "退款金额不能大于订单金额");
        }

        // 限制退款时间最大为7天，防止订单已经分润结算
        // 获取当前时间
        Date now = new Date();
        // 获取订单的支付时间
        Date payTime = order.getPayTime();
        // 创建 Calendar 实例，用于计算7天后的时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(payTime);
        calendar.add(Calendar.DAY_OF_YEAR, 7);
        // 检查支付时间是否超过7天
        if (calendar.getTime().before(now)) {
            throw new BusinessException(500, "超过7天的订单无法退款");
        }

        // 保存退款订单信息
        Refund refund = new Refund();
        refund.setShopId(order.getShopId());
        refund.setOrderId(order.getId());
        refund.setAmount(refundOrderParam.getRefundFee());
        refund.setRefundNo("T" + StringUtil.getStrNo());
        refund.setRefundDesc(refundOrderParam.getRefundDesc());
        refund.setStatus(0);
        refund.setCreateBy(LoginUtil.getUserId());
        refundMapper.insert(refund);

        // 保存退款商品信息
        for (RefundGoodsParam refundGoodsParam : refundOrderParam.getGoodsList()) {
            // 获取订单商品信息
            OrderDetail orderDetail = orderDetailMapper.selectOne(Wrappers.lambdaQuery(OrderDetail.class)
                    .eq(OrderDetail::getOrderId, order.getId())
                    .eq(OrderDetail::getGoodsId, refundGoodsParam.getGoodsId()));
            if (ObjectUtil.isNull(orderDetail) || orderDetail.getNumber() < refundGoodsParam.getNumber()) {
                throw new BusinessException(500, "商品信息异常");
            }

            // 保存退款订单详情
            RefundDetail refundDetail = new RefundDetail();
            BeanUtils.copyProperties(orderDetail, refundDetail);
            refundDetail.setRefundId(refund.getId());
            refundDetail.setNumber(refundGoodsParam.getNumber());
            refundDetailMapper.insert(refundDetail);
        }

        //生成微信单号
        WxRefundRequestParam wxRefundRequestParam = new WxRefundRequestParam();
        //退款单号
        wxRefundRequestParam.setOutRefundNo(refund.getRefundNo());
        //商户单号
        wxRefundRequestParam.setOutTradeNo(order.getOrderNo());
        //订单总金额
        wxRefundRequestParam.setTotalFee(order.getAmount().multiply(new BigDecimal(100)).intValue());
        //退款金额
        wxRefundRequestParam.setRefundFee(refundOrderParam.getRefundFee().multiply(new BigDecimal(100)).intValue());
        //退款原因
        wxRefundRequestParam.setRefundDesc(refundOrderParam.getRefundDesc());

        Map<String, String> result = wxPayService.refund(wxRefundRequestParam);
        log.info("微信退款结果：{}", JSONObject.toJSONString(result));

//        if ("SUCCESS".equals(result.get("return_code"))
//                && "SUCCESS".equals(result.get("result_code"))) {
        if (true) {
            // 判断是否是全额退款
//            if (order.getAmount().compareTo(beforeRefundFee.add(refundOrderParam.getRefundFee())) == 0) {
//                order.setStatus(3);
//            } else {
//                order.setStatus(4);
//            }
            // 业务要求全部显示为已退款
            order.setStatus(3);
            orderMapper.updateById(order);
            order.setRefundAmount(beforeRefundFee.add(refundOrderParam.getRefundFee()));
            order.setActualAmount(order.getAmount().subtract(order.getRefundAmount()));
            orderMapper.updateById(order);

            // 如果是退商品还需要扣减订单详情里面的商品数量
            for (RefundGoodsParam refundGoodsParam : refundOrderParam.getGoodsList()) {
                // 获取订单商品信息
                OrderDetail orderDetail = orderDetailMapper.selectOne(Wrappers.lambdaQuery(OrderDetail.class)
                        .eq(OrderDetail::getOrderId, order.getId())
                        .eq(OrderDetail::getGoodsId, refundGoodsParam.getGoodsId()));
                if (ObjectUtil.isNull(orderDetail) || orderDetail.getNumber() < refundGoodsParam.getNumber()) {
                    throw new BusinessException(500, "商品信息异常");
                }

                orderDetail.setNumber(orderDetail.getNumber() - refundGoodsParam.getNumber());
                orderDetailMapper.updateById(orderDetail);
            }
            // 退款后需要重新计算订单分润
            // 此处用来处理代理商当天分润，不一定准确，最终分润以定时任务统计为准
            CommissionOrderMq agentCommissionMq = new CommissionOrderMq();
            agentCommissionMq.setShopId(order.getShopId());
            agentCommissionMq.setAmount(refund.getAmount().negate());// 退款将金额设置为负数
            agentCommissionMq.setOrderId(order.getId());
            agentCommissionMq.setPayTime(refund.getCreateTime());
            SendResult sendResult = rocketMQTemplate.syncSend(RocketMqConstant.AGENT_COMMISSION_TOPIC, JSON.toJSONString(agentCommissionMq), 3000);
            log.info(RocketMqConstant.AGENT_COMMISSION_TOPIC + " 推送到队列结果：" + sendResult);

            //插入退款单信息
            refund.setStatus(1);
            refund.setWxRefundId(result.get("refund_id"));
            refundMapper.updateById(refund);
            return true;
        } else {
            refund.setStatus(2);
            refund.setErrorDesc(result.get("err_code_des"));
            refundMapper.updateById(refund);
            throw new BusinessException(500, result.get("err_code_des"));
        }
    }

    @Override
    public RefundInfoVo getRefundInfo(String refundNo) {
        // 获取退款信息
        Refund refund = refundMapper.selectOne(Wrappers.lambdaQuery(Refund.class)
                .eq(Refund::getRefundNo, refundNo));
        if (refund == null) {
            throw new BusinessException("退款信息异常");
        }
        // 获取对应的订单信息
        Order order = orderMapper.selectById(refund.getOrderId());
        if (order == null) {
            throw new BusinessException("订单信息异常");
        }
        RefundInfoVo refundInfoVo = new RefundInfoVo();
        BeanUtils.copyProperties(order, refundInfoVo);
        BeanUtils.copyProperties(refund, refundInfoVo);
        refundInfoVo.setRefundAmount(refund.getAmount());
        // 获取订单退款详情
        List<RefundDetailVo> refundDetailVos = refundDetailMapper.getRefundDetailVoByRefundId(refund.getId());
        refundInfoVo.setRefundDetailList(refundDetailVos);

        return refundInfoVo;
    }

    @Override
    public Integer queryStatus(String orderNo) throws Exception {
        // 通过redis防止重复提交
        if (redisUtil.hasKey(CommonConstant.ORDER_QUERY_CHECK + orderNo)) {
            throw new BusinessException(500, "查询频率过快，请稍后再操作");
        }
        redisUtil.set(CommonConstant.ORDER_QUERY_CHECK + orderNo, 1, 1);
        // 根据订单号获取订单信息
        Order order = orderMapper.selectOne(
                Wrappers.lambdaQuery(Order.class).eq(Order::getOrderNo, orderNo));
        if (order == null) {
            throw new BusinessException("订单信息异常");
        }
        if (order.getStatus() == 0) {
            // 先去支付渠道查询一下订单状态，确认未支付则关闭订单
            WxQueryRequestParam wxQueryRequestParam = new WxQueryRequestParam();
            wxQueryRequestParam.setOutTradeNo(order.getOrderNo());
            Map<String, String> resultMap = wxPayService.orderQuery(wxQueryRequestParam);
            log.info("微信查询结果：" + JSONObject.toJSONString(resultMap));
            if ("SUCCESS".equals(resultMap.get("return_code")) && "SUCCESS".equals(resultMap.get("result_code"))
                    && "SUCCESS".equals(resultMap.get("trade_state"))) {
                // 如果已支付修改订单状态为已支付
                order.setStatus(1);
                //支付时间
                DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
                Date payTime = df.parse(resultMap.get("time_end"));
                order.setPayTime(payTime);
                //微信订单号
                order.setWxTransactionId(resultMap.get("transaction_id"));
                orderMapper.updateById(order);

                // 此处用来处理代理商当天分润，不一定准确，最终分润以定时任务统计为准
                CommissionOrderMq agentCommissionMq = new CommissionOrderMq();
                agentCommissionMq.setShopId(order.getShopId());
                agentCommissionMq.setAmount(order.getAmount());
                agentCommissionMq.setOrderId(order.getId());
                agentCommissionMq.setPayTime(order.getPayTime());
                SendResult sendResult = rocketMQTemplate.syncSend(RocketMqConstant.AGENT_COMMISSION_TOPIC, JSON.toJSONString(agentCommissionMq), 3000);
                log.info(RocketMqConstant.AGENT_COMMISSION_TOPIC + " 推送到队列结果：" + sendResult);
            }
        }

        return order.getStatus();
    }

}
